package com.hxx.widget.richtext.toolbar

import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.Typeface
import android.text.*
import android.text.style.*
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.content.res.ResourcesCompat
import androidx.core.text.getSpans
import com.hxx.widget.R
import com.hxx.widget.SoftWindowStateListener
import com.hxx.widget.loadFromLayoutId
import com.hxx.widget.richtext.RichPlatte
import com.hxx.widget.richtext.Style
import com.hxx.widget.richtext.views.NumberBulletSpan
import com.hxx.widget.softInputWindowListener
import kotlinx.android.synthetic.main.widget_layout_richtext_style.view.*

/**
 * 功能：
 * 1.样式预览
 * 2.解析光标位置样式
 * 3.获取当前样式
 */
class RichTextStyleMenu @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr), OnClickListener, SoftWindowStateListener,
    SeekBar.OnSeekChangedListener, RichPlatte {
    private val TAG = "文本样式菜单栏"
    private var currentSettingStyle = Style()
    private var fontScaleSizes = floatArrayOf(0.5f, 0.8f, 1f, 1.2f, 1.5f) //文本大小有5种缩放大小尺寸

    private var settingListener: StyleListener = object : StyleListener {

        override fun onBoldChanged(enable: Boolean) {
            currentSettingStyle.bold = enable
        }

        override fun onItalicChanged(enable: Boolean) {
            currentSettingStyle.italic = enable
        }

        override fun onUnderlineChanged(enable: Boolean) {
            currentSettingStyle.underline = enable
        }

        override fun onStrikeThroughChanged(enable: Boolean) {
            currentSettingStyle.strikeThrough = enable
        }

        override fun onListOrderChanged(enable: Boolean) {
            currentSettingStyle.isListOrder = enable
        }

        override fun onAlignmentChanged(alignment: Layout.Alignment) {
            currentSettingStyle.alignment = alignment
        }

        override fun onColorChanged(color: Int) {
            currentSettingStyle.color = color
        }

        override fun onFontSizeChanged(scale: Float) {
            currentSettingStyle.fontSizeScale = scale
        }
    }

    private val listeners = arrayListOf<StyleListener>()
    private val colors = intArrayOf(
        ResourcesCompat.getColor(resources, R.color.widget_color_black, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_red, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_orange, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_yellow, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_green, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_cyan, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_blue, context.theme),
        ResourcesCompat.getColor(resources, R.color.widget_color_purple, context.theme),
    )

    init {
        orientation = VERTICAL
        loadFromLayoutId(R.layout.widget_layout_richtext_style).apply {
            widget_rich_blod.setOnClickListener(this@RichTextStyleMenu)
            widget_rich_italic.setOnClickListener(this@RichTextStyleMenu)
            widget_rich_underline.setOnClickListener(this@RichTextStyleMenu)
            widget_rich_strikeThrough.setOnClickListener(this@RichTextStyleMenu)
            collectionRadios(widget_rich_left, widget_rich_center, widget_rich_right)
            widget_rich_list_unorder.setOnClickListener(this@RichTextStyleMenu)
            widget_rich_seekBar.seekListener = this@RichTextStyleMenu
            widget_rich_apply.setOnClickListener(this@RichTextStyleMenu)
            var fontSizeIndex = 0
            fontScaleSizes.forEachIndexed { index, fl ->
                if (fl == 1f) {
                    fontSizeIndex = index
                    return@forEachIndexed
                }
            }

            widget_rich_seekBar.applyMaxPoint(fontScaleSizes.size, fontSizeIndex)
            createRadios(widget_rich_palette)
        }
        softInputWindowListener(this)
        listeners.add(settingListener)
    }


    fun addStyleListener(listener:StyleListener){
        listeners.add(listener)
    }

    private fun collectionRadios(vararg items: View) {
        val clickListener = OnClickListener {
            items.forEach { child ->
                child.isSelected = child == it
            }
            when (it) {
                widget_rich_left -> {
                    listeners.forEach {
                        it.onAlignmentChanged(Layout.Alignment.ALIGN_NORMAL)
                    }
                }
                widget_rich_center -> {
                    listeners.forEach {
                        it.onAlignmentChanged(Layout.Alignment.ALIGN_CENTER)
                    }
                }
                widget_rich_right -> {
                    listeners.forEach {
                        it.onAlignmentChanged(Layout.Alignment.ALIGN_OPPOSITE)
                    }
                }
            }
        }
        widget_rich_left.isSelected = true
        items.forEach {
            it.setOnClickListener(clickListener)
        }
    }

    /**
     * 单选调色盘
     */
    private fun createRadios(parent: ViewGroup) {
        val childClick = OnClickListener {
            val old = currentSettingStyle.color
            for (i in 0 until parent.childCount) {
                val child = parent.getChildAt(i)
                if (child == it) {
                    child.isSelected = true
                    if (old != colors[i]) {
                        listeners.forEach {
                            it.onColorChanged(colors[i])
                        }
                    }
                } else {
                    child.isSelected = false
                }
            }
        }
        for (i in 0 until parent.childCount) {
            val child = parent.getChildAt(i)
            child.isSelected = i == 0
            child.setOnClickListener(childClick)
        }
    }

    /**
     * 文本缩进
     */
//    private fun textIndentRadio() {
//        // maxIndentLevel = 5
//        val click = OnClickListener {
//            val increaseLevelDrawable = widget_rich_indent_increase.drawable as LevelListDrawable
//            val decreaseLevelDrawable = widget_rich_indent_decrease.drawable as LevelListDrawable
//            val oldLevel = increaseLevelDrawable.level
//            if (it == widget_rich_indent_increase) {
//                val maxLevel = maxIndentLevel
//                val targetIncreaseLevel = increaseLevelDrawable.level + 1
//                if (targetIncreaseLevel <= maxLevel) {
//                    increaseLevelDrawable.level = targetIncreaseLevel
//                    decreaseLevelDrawable.level = targetIncreaseLevel
//                }
//            } else {
//                val minLevel = 0
//                val targetDecreaseLevel = increaseLevelDrawable.level - 1
//                if (targetDecreaseLevel >= minLevel) {
//                    increaseLevelDrawable.level = targetDecreaseLevel
//                    decreaseLevelDrawable.level = targetDecreaseLevel
//                }
//            }
//            val currentLevel = increaseLevelDrawable.level
//            if (oldLevel != currentLevel) {
//                styleSettingListener.onIndentChanged(currentLevel)
//            }
//            updatePreview()
//        }
//        widget_rich_indent_decrease.setOnClickListener(click)
//        widget_rich_indent_increase.setOnClickListener(click)
//    }

    override fun onClick(v: View) {
        v.isSelected = !v.isSelected
        when (v) {
            widget_rich_blod -> {
                listeners.forEach {
                    it.onBoldChanged(v.isSelected)
                }
            }
            widget_rich_italic -> {
                listeners.forEach {
                    it.onItalicChanged(v.isSelected)
                }
            }
            widget_rich_underline -> {
                listeners.forEach {
                    it.onUnderlineChanged(v.isSelected)
                }
            }
            widget_rich_strikeThrough -> {
                listeners.forEach {
                    it.onStrikeThroughChanged(v.isSelected)
                }
            }
            widget_rich_list_unorder -> {
                listeners.forEach {
                    it.onListOrderChanged(v.isSelected)
                }
            }
            widget_rich_apply -> {
//                sendStyleChanged()
//                visibility = View.GONE
            }
        }
    }

    /**
     * 当前文本样式
     */
    private fun applyStyles() {
        updateViewState()
    }

    /**
     * 更新视图组件状态
     */
    private fun updateViewState() {
        updateCharacterStyleView(currentSettingStyle)
        updateParagraphStyleView(currentSettingStyle)
    }

    /**
     * 字符样式
     */
    private fun updateCharacterStyleView(style: Style) {
        widget_rich_blod.isSelected = style.bold
        widget_rich_italic.isSelected = style.italic
        widget_rich_underline.isSelected = style.underline
        widget_rich_strikeThrough.isSelected = style.strikeThrough

        var fontSizeSelectedIndex = 0
        fontScaleSizes.forEachIndexed { index, fl ->
            if (fl == style.fontSizeScale) {
                fontSizeSelectedIndex = index
                return@forEachIndexed
            }
        }
        widget_rich_seekBar.applyMaxPoint(fontScaleSizes.size, fontSizeSelectedIndex)

        var colorIndex = 0

        colors.forEachIndexed { index, i ->
            if (i == style.color) {
                colorIndex = index
                return@forEachIndexed
            }
        }

        for (i in 0 until widget_rich_palette.childCount) {
            val child = widget_rich_palette.getChildAt(i)
            child.isSelected = colorIndex == i
        }
    }

    /**
     * 段落样式
     */
    private fun updateParagraphStyleView(style: Style) {
        widget_rich_list_unorder.isSelected = style.isListOrder
        when (style.alignment) {
            Layout.Alignment.ALIGN_NORMAL -> {
                widget_rich_left.isSelected = true
                widget_rich_center.isSelected = false
                widget_rich_right.isSelected = false
            }
            Layout.Alignment.ALIGN_CENTER -> {
                widget_rich_left.isSelected = false
                widget_rich_center.isSelected = true
                widget_rich_right.isSelected = false
            }
            Layout.Alignment.ALIGN_OPPOSITE -> {
                widget_rich_left.isSelected = false
                widget_rich_center.isSelected = false
                widget_rich_right.isSelected = true
            }
        }
    }


    override fun onSoftWindowOpen(visibleRect: Rect, localRect: Rect) {
        Log.i(TAG, "onSoftWindowOpen: 键盘弹起")
//        visibility = View.GONE
    }

    override fun onSoftWindowClose(visibleRect: Rect, localRect: Rect) {
        Log.i(TAG, "onSoftWindowOpen: 键盘关闭")
//        visibility = View.VISIBLE
    }

    override fun onPercentChanged(percent: Int) {
    }

    override fun onPointChanged(point: Int) {
        currentSettingStyle.fontSizeScale = fontScaleSizes[point]
    }
    interface StyleListener {
        fun onBoldChanged(enable: Boolean)
        fun onItalicChanged(enable: Boolean)
        fun onUnderlineChanged(enable: Boolean)
        fun onStrikeThroughChanged(enable: Boolean)
        fun onListOrderChanged(enable: Boolean)
        fun onAlignmentChanged(alignment: Layout.Alignment)
        fun onColorChanged(color: Int)
        fun onFontSizeChanged(scale: Float)
    }

    override fun applySpans(spans: List<*>) {
        currentSettingStyle = Style()
        currentSettingStyle.apply {
            spans.forEach { span ->
                when (span) {
                    is AlignmentSpan -> {
                        if (alignment != span.alignment) {
                            alignment = span.alignment
                        }
                    }
                    is NumberBulletSpan -> {
                        isListOrder = true
                    }
                    is ForegroundColorSpan -> {
                        color = span.foregroundColor
                    }
                    is StyleSpan -> {
                        when (span.style) {
                            Typeface.NORMAL -> {
                                bold = false
                                italic = false
                            }
                            Typeface.BOLD -> {
                                bold = true
                                italic = false
                            }
                            Typeface.ITALIC -> {
                                bold = false
                                italic = true
                            }
                            Typeface.BOLD_ITALIC -> {
                                bold = true
                                italic = true
                            }
                        }
                    }
                    is RelativeSizeSpan -> {
                        fontSizeScale = span.sizeChange
                    }
                    is UnderlineSpan -> {
                        underline = true
                    }
                    is StrikethroughSpan -> {
                        strikeThrough = true
                    }
                }
            }
        }
        applyStyles()
    }

    override fun onSelectionChanged(editable: Editable) {
        val start = Selection.getSelectionStart(editable)
        val characterSpans =
            editable.getSpans(Math.max(0, start - 1), start, CharacterStyle::class.java)
        val paragraphSpans =
            editable.getSpans(Math.max(0, start - 1), start, ParagraphStyle::class.java)
        val all = arrayListOf<Any>()
        all.addAll(characterSpans)
        all.addAll(paragraphSpans)
        applySpans(all)
    }

    override fun getCharacterStyle(): List<Any> {
        val result = arrayListOf<Any>()
        currentSettingStyle.apply {
            if (color != Color.BLACK){
                result.add(ForegroundColorSpan(color))
            }
            if (bold && italic) {
                result.add(StyleSpan(Typeface.BOLD_ITALIC))
            } else if (bold && !italic) {
                result.add(StyleSpan(Typeface.BOLD))
            } else if (!bold && italic) {
                result.add(StyleSpan(Typeface.ITALIC))
            }
            if (fontSizeScale != 1f) {
                result.add(RelativeSizeSpan(fontSizeScale))
            }
            if (underline) {
                result.add(UnderlineSpan())
            }
            if (strikeThrough) {
                result.add(StrikethroughSpan())
            }
        }
        return result
    }

    override fun getParagraphStyle(): List<Any> {
        val result = arrayListOf<Any>()
        currentSettingStyle.apply {
            if (alignment != Layout.Alignment.ALIGN_NORMAL) {
                result.add(AlignmentSpan.Standard(alignment))
            }
            if (isListOrder) {
                result.add(NumberBulletSpan(1))
            }
        }
        return result
    }

    override fun shouldUpdateStyle(editable: Editable, start: Int, end: Int): Boolean {
        currentSettingStyle.apply {
            val styleSpans = editable.getSpans<StyleSpan>(start, end)
            styleSpans.forEach {
                if (bold && italic) {
                    if (it.style != Typeface.BOLD_ITALIC) {
                        return true
                    }
                } else if (bold && !italic) {
                    if (it.style != Typeface.BOLD) {
                        return true
                    }
                } else if (!bold && italic) {
                    if (it.style != Typeface.ITALIC) {
                        return true
                    }
                } else {
                    if (it.style != Typeface.NORMAL) {
                        return true
                    }
                }
            }
            if (styleSpans.isEmpty() && bold.or(italic)) {
                return true
            }
            val textColorSpans = editable.getSpans<ForegroundColorSpan>(start, end)
            textColorSpans.forEach {
                if (it.foregroundColor != color) {
                    return true
                }
            }
            if (textColorSpans.isEmpty() && color != Color.BLACK) {
                return true
            }
            val underLineSpans = editable.getSpans<UnderlineSpan>(start, end)
            if (underLineSpans.isEmpty() && underline){
                return true
            }
            if (underLineSpans.isNotEmpty() && !underline){
                return true
            }
            val strikethroughSpan = editable.getSpans<StrikethroughSpan>(start, end)
            if (strikethroughSpan.isEmpty() && strikeThrough){
                return true
            }
            if (strikethroughSpan.isNotEmpty() && !strikeThrough){
                return true
            }

            val relativeSizeSpan = editable.getSpans<RelativeSizeSpan>(start, end)
            if (relativeSizeSpan.isEmpty() && fontSizeScale != 1f){
                return true
            }
            if (relativeSizeSpan.isNotEmpty() && fontSizeScale == 1f){
                return true
            }
        }
        return false
    }
}